package com.bwie.service.impl;

import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.es.EsUser;
import com.bwie.poi.StringUtils;
import com.bwie.pojo.TbLog;
import com.bwie.pojo.TbMenu;
import com.bwie.pojo.TbProd;
import com.bwie.pojo.TbUser;
import com.bwie.service.TbUserService;
import com.bwie.mapper.TbUserMapper;
import com.bwie.state.CheckUser;
import com.bwie.utils.R;
import com.bwie.vo.AdminLoginVo;
import com.bwie.vo.PageInfoVo;
import com.bwie.vo.UserPageVo;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 28242
 * @description 针对表【tb_user(用户表)】的数据库操作Service实现
 * @createDate 2025-04-21 16:05:48
 */
@Service
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser>
        implements TbUserService {

    @Autowired
    HttpServletRequest request;

    @Autowired
    TbUserMapper tbUserMapper;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    FastFileStorageClient fastFileStorageClient;

    @Autowired
    KafkaTemplate kafkaTemplate;

    @Autowired
    JavaMailSender javaMailSender;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public R getUserById(Integer id) {
        TbUser tbUser = tbUserMapper.selectById(id);
        if (tbUser == null) {
            return R.ERROR(404, "用户不存在");
        }

        tbUser.setUserPass(null);
        return R.OK(tbUser);
    }

    @Override
    public R adminlogin(AdminLoginVo adminLoginVo) {

        TbLog tbLog = new TbLog();
        tbLog.setCreateTime(new Date());
        tbLog.setLogName("登录");
        tbLog.setIp(request.getRemoteAddr());
        tbLog.setLogType(1);
        String message="";

        LambdaQueryWrapper<TbUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TbUser::getUserName, adminLoginVo.getUserName());
        TbUser tbUser = tbUserMapper.selectOne(wrapper);
        if (ObjectUtil.isEmpty(tbUser)) {

            message="用户不存在:登录账号("+adminLoginVo.getUserName()+")登录密码:("+adminLoginVo.getUserPass()+")";
            tbLog.setLogContent(message);
            kafkaTemplate.send("topic-log",JSON.toJSONString(tbLog));
            return R.ERROR(404, "账号不存在");
        }
        if (!tbUser.getUserPass().equals(adminLoginVo.getUserPass())) {
            message="密码错误:登录账号("+adminLoginVo.getUserName()+")登录密码:("+adminLoginVo.getUserPass()+")";
            tbLog.setLogContent(message);
            kafkaTemplate.send("topic-log",JSON.toJSONString(tbLog));

            return R.ERROR(500, "密码错误");
        }



        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "123456")
                .claim("userId", tbUser.getUserId())
                .claim("userName", tbUser.getUserName())
                .claim("nickName", tbUser.getNickName())
                .compact();

        String redisKey = "token-" + tbUser.getUserId();
        redisTemplate.opsForValue().set(redisKey, token, 60, TimeUnit.MINUTES);

        tbUser.setToken(token);
        tbUser.setUserPass(null);
        message="登录成功:登录账号("+adminLoginVo.getUserName()+")登录密码:("+adminLoginVo.getUserPass()+")";
        tbLog.setLogContent(message);
        kafkaTemplate.send("topic-log",JSON.toJSONString(tbLog));

        return R.OK(tbUser);
    }

    @Override
    public R getUserlist(PageInfoVo pageInfoVo) {

        //构造分页参数
        Page<TbUser> page = new Page<>(pageInfoVo.getPageNum(), pageInfoVo.getPageSize());


        QueryWrapper<TbUser> wrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(pageInfoVo.getKeyWord())) {

            wrapper.lambda()
                    .like(TbUser::getUserName, pageInfoVo.getKeyWord())
                    .or()
                    .like(TbUser::getNickName, pageInfoVo.getKeyWord())
                    .or()
                    .like(TbUser::getUserMobile, pageInfoVo.getKeyWord());
        }
        wrapper.lambda().orderByDesc(TbUser::getUserId);

        Page<TbUser> tbUserPage = tbUserMapper.selectPage(page, wrapper);
        return R.OK(tbUserPage);

    }

    @Override
    public R userReg(TbUser tbUser) {

        TbUser user = tbUserMapper.selectOne(new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserName, tbUser.getUserName()));
        if (user != null) {
            return R.ERROR(404, "用户名重复");
        }
        tbUser.setCreateTime(new Date());
        tbUserMapper.insert(tbUser);

        return R.OK();
    }

    @Override
    public R checkUser(TbUser tbUser) {

        TbUser user = tbUserMapper.selectById(tbUser.getUserId());
        if (user == null) {
            return R.ERROR(404, "该商户不存在");
        }

        if (tbUser.getUserStatus().equals(CheckUser.CHECK_NO.getCode())) {
            if (StringUtils.isEmpty(tbUser.getReasion())) {
                return R.ERROR(404, "请填写驳回理由");
            }
        }
        tbUser.setUserStatus(tbUser.getUserStatus());
        tbUser.setReasion(tbUser.getReasion());
        tbUserMapper.updateById(tbUser);
        //发送通知（如果审核通过发送短信，不通过发送邮箱）

        String message = JSON.toJSONString(tbUser);
        kafkaTemplate.send("topic-user", message);


        return R.OK();
    }

    @Override
    public R getUserInfo() {

        String token = request.getHeader("token");

        Integer userId = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody().get("userId", Integer.class);

        TbUser tbUser = tbUserMapper.selectById(userId);

        return R.OK(tbUser);
    }

    @Override
    public R updateUser(TbUser tbUser) {

        TbUser user = tbUserMapper.selectById(tbUser.getUserId());

        if (user == null) {
            return R.ERROR(500, "用户不存在");
        }
        tbUserMapper.updateById(tbUser);

        return R.OK();
    }

    @Override
    public R uploadFile(MultipartFile file) {

        try {
            String extName = FileNameUtil.extName(file.getOriginalFilename());
            StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), extName, null);

            String url = "http://192.168.80.192:8888/" + storePath.getFullPath();
            return R.OK(url);
        } catch (IOException e) {
            e.printStackTrace();
            return R.ERROR(500, "上传失败");
        }
    }

    @Override
    public R deleteUserById(Integer userId) {

        TbUser user = tbUserMapper.selectById(userId);
        if (user == null) {
            return R.ERROR(404, "用户不存在不能删除");
        }

        tbUserMapper.deleteById(userId);
        return R.OK();
    }

    @Override
    public R deleteAll(List<TbUser> userList) {

        for (TbUser user : userList) {
            tbUserMapper.deleteById(user.getUserId());
        }

        return R.OK();
    }

    @Override
    public R getMyRolelist() {

        String token = request.getHeader("token");

        if (token == null) {
            return R.ERROR(404, "请先登录");
        }

        Integer userId = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody().get("userId", Integer.class);

        List<String> roleList = tbUserMapper.getUserRoleList(userId);


        return R.OK(roleList);
    }

    @Override
    public R getUserMenuTree() {
        String token = request.getHeader("token");

        if (token == null) {
            return R.ERROR(404, "请先登录");
        }

        Integer userId = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody().get("userId", Integer.class);


        List<TbMenu> listAll = tbUserMapper.getUserMenuTree(userId);


        //工具类
//        List<Tree<String>> treeList = TreeUtil.build(list, "0", (menu, tree) -> {
//
//            tree.setId(menu.getMenuId() + "");
//            tree.setName(menu.getMenuName());
//            tree.setParentId(menu.getMenuPid() + "");
//
//            tree.putExtra("menuPath", menu.getMenuPath());
//
//        });

        ArrayList<TbMenu> root = new ArrayList<>();
        for (TbMenu tbMenu : listAll) {
            if (tbMenu.getMenuPid() == 0) {
                root.add(tbMenu);
            }
        }
        //使用递归
        buildTree(root, listAll);
        return R.OK(root);
    }

    @Override
    public R getUserListsFormEs(UserPageVo userPageVo) {
        //1.分页信息

        Integer pageNum = 0;
        if (userPageVo.getPageNum() != null && userPageVo.getPageNum() > 0) {
            pageNum = userPageVo.getPageNum() - 1;
        }
        PageRequest pageRequest = PageRequest.of(pageNum, userPageVo.getPageSize());


        //2构造搜索条件

        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//        boolQueryBuilder.must(
//                QueryBuilders.matchAllQuery()
//        );
        //多条件查询
        if (StringUtils.isNotEmpty(userPageVo.getKeyWord())) {
            boolQueryBuilder.should(
                    QueryBuilders.matchQuery("userName", userPageVo.getKeyWord())
            );
            boolQueryBuilder.should(
                    QueryBuilders.matchQuery("nickName", userPageVo.getKeyWord())
            );
            boolQueryBuilder.should(
                    QueryBuilders.matchQuery("userMobile", userPageVo.getKeyWord())
            );
            boolQueryBuilder.should(
                    QueryBuilders.matchQuery("userEmail", userPageVo.getKeyWord())
            );
        }
        //排序
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("userId").order(SortOrder.DESC);

        //高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("nickName").preTags("<font color='red'>").postTags("</font>");


        //3.开始查询(集成分参数和搜索条件)
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder
                .withPageable(pageRequest)
                .withSort(sortBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withQuery(boolQueryBuilder);
        SearchHits<EsUser> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsUser.class);


        //4.读取查询结果
        Long total = searchHits.getTotalHits();
        ArrayList<EsUser> records = new ArrayList<>();

        for (SearchHit<EsUser> searchHit : searchHits.getSearchHits()) {
            EsUser esUser = searchHit.getContent();
            List<String> nickNamelist = searchHit.getHighlightField("nickName");
            if (nickNamelist !=null && nickNamelist.size()>0){
                String nickName = nickNamelist.get(0);
                esUser.setNickName(nickName);
            }
            records.add(esUser);
        }

        //5返回结果
        HashMap<String, Object> map = new HashMap<>();
        map.put("total", total);
        map.put("records", records);


        return R.OK(map);
    }

    private void buildTree(List<TbMenu> root, List<TbMenu> listAll) {

        for (TbMenu rootMenu : root) {
            ArrayList<TbMenu> children = new ArrayList<>();
            for (TbMenu subMenu : listAll) {
                if (subMenu.getMenuPid().equals(rootMenu.getMenuId())) {
                    children.add(subMenu);
                }
            }
            rootMenu.setChildren(children);

            buildTree(children, listAll);
        }

    }

    @KafkaListener(topics = "topic-user")
    public void recordMessage(String message, Acknowledgment acknowledgment) {
        System.out.println("接受消息:" + message);

        TbUser tbUser = JSON.parseObject(message, TbUser.class);

        if (tbUser.getUserStatus().equals(CheckUser.CHECK_OK.getCode())) {
            String mobile = tbUser.getUserMobile();
            String content = "恭喜宁的长啊后通过";
            System.out.println("发送短信");
            acknowledgment.acknowledge();
        } else if (tbUser.getUserStatus().equals(CheckUser.CHECK_NO.getCode())) {
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();

            try {
                MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
                mimeMessageHelper.setFrom("2824218818@qq.com");

                mimeMessageHelper.setTo(tbUser.getUserEmail());

                mimeMessageHelper.setSubject("用户审核驳回");

                mimeMessageHelper.setText("您的账号审核被驳回，请重新注册");

                javaMailSender.send(mimeMessage);
                System.out.println("发送邮箱成功");
                acknowledgment.acknowledge();
            } catch (MessagingException e) {
                e.printStackTrace();
//                throw new RuntimeException(e);
            }
        }
    }

    @KafkaListener(topics = "topic-shop")
    public void recvprodMessage(String message, Acknowledgment acknowledgment) {

        System.out.println("接收消息；" + message);

        TbProd tbProd = JSON.parseObject(message, TbProd.class);

        if (tbProd.getProdStatus() == 2) {
            //发送短信
            TbUser tbUser = tbUserMapper.selectById(tbProd.getUserId());

            String count = "你的商品已经审核通过";
            String moble = tbUser.getUserMobile();
            System.out.println("发送短信");
            acknowledgment.acknowledge();
        } else if (tbProd.getProdStatus() == 3) {
            TbUser tbUser = tbUserMapper.selectById(tbProd.getUserId());
            String userEmail = tbUser.getUserEmail();
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();

            try {
                MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);

                messageHelper.setFrom("2824218818@qq.com");

                messageHelper.setTo(tbUser.getUserEmail());

                messageHelper.setSubject("商品审核驳回");

                messageHelper.setText("您的商品" + tbProd.getProdName() + "审核被驳回");

                javaMailSender.send(mimeMessage);
                acknowledgment.acknowledge();
            } catch (MessagingException e) {
                e.printStackTrace();
//                throw new RuntimeException(e);
            }
        }
    }

}




